package com.uduemc.biso.node.web.interceptor;

import java.io.IOException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.uduemc.biso.node.core.common.dto.FeignPageUtil;
import com.uduemc.biso.node.core.common.entities.SRHtml;
import com.uduemc.biso.node.core.common.entities.SitePage;
import com.uduemc.biso.node.core.common.entities.SiteSearchPage;
import com.uduemc.biso.node.core.common.entities.sitepage.PageType;
import com.uduemc.biso.node.core.common.exception.SitePageException;
import com.uduemc.biso.node.core.common.utils.PageUtil;
import com.uduemc.biso.node.core.entities.HRedirectUrl;
import com.uduemc.biso.node.core.entities.SCategories;
import com.uduemc.biso.node.core.entities.SCodePage;
import com.uduemc.biso.node.core.entities.SPage;
import com.uduemc.biso.node.core.entities.SSeoCategory;
import com.uduemc.biso.node.core.entities.SSeoPage;
import com.uduemc.biso.node.core.entities.SSystem;
import com.uduemc.biso.node.core.entities.SSystemItemCustomLink;
import com.uduemc.biso.node.web.component.RequestHolder;
import com.uduemc.biso.node.web.component.SiteHolder;
import com.uduemc.biso.node.web.component.SpringContextUtils;
import com.uduemc.biso.node.web.entities.AccessPage;
import com.uduemc.biso.node.web.exception.NotFound404Exception;
import com.uduemc.biso.node.web.exception.NotFoundSiteCategoryException;
import com.uduemc.biso.node.web.exception.NotFoundSitePageException;
import com.uduemc.biso.node.web.exception.NotScreenSystemPageException;
import com.uduemc.biso.node.web.service.VirtualFolderService;
import com.uduemc.biso.node.web.service.byfeign.CategoryService;
import com.uduemc.biso.node.web.service.byfeign.CodeService;
import com.uduemc.biso.node.web.service.byfeign.PageService;
import com.uduemc.biso.node.web.service.byfeign.RedirectUrlService;
import com.uduemc.biso.node.web.service.byfeign.SeoService;
import com.uduemc.biso.node.web.service.byfeign.SysStaticDataService;
import com.uduemc.biso.node.web.service.byfeign.SystemService;
import com.uduemc.biso.node.web.utils.StringFilterUtil;

import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HtmlUtil;

/**
 * 通过访问的uri链接验证访问的页面，通过获取到页面后，对应的page、seo、以及系统页面的系统数据信息获取
 * 
 * @author guanyi
 *
 */
@Component
public class PageInterceptor implements HandlerInterceptor {

	private static final Logger logger = LoggerFactory.getLogger(PageInterceptor.class);

	@Autowired
	private RequestHolder requestHolder;

	@Autowired
	private SiteHolder siteHolder;

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws JsonParseException, JsonMappingException, NotFound404Exception, NotFoundSitePageException, SitePageException, JsonProcessingException,
			NotScreenSystemPageException, NotFoundSiteCategoryException, IOException {

		// 获取页面数据
		PageUtil pageUtil = new PageUtil(requestHolder.getAccessSite().getUri());
		if (!pageUtil.matchPage()) {
			return notFoundSitePageExceptionOr404RedirectUrl("无法识别页面！ siteUri: " + requestHolder.getAccessSite().getUri(), response);
		}

		if (pageUtil.isSearchPage()) {
			return searchPage(pageUtil, request);
		}

		return page(pageUtil, response);
	}

	protected boolean searchPage(PageUtil pageUtil, HttpServletRequest request) {
		SitePage sitePage = new SitePage();

		SiteSearchPage siteSearchPage = new SiteSearchPage();
		String keyword = StringFilterUtil.keywordFilter(request.getParameter("kw"));
		if (StrUtil.isNotBlank(keyword)) {
			siteSearchPage.setKeyword(keyword);
		}

		String pgi = HtmlUtil.escape(request.getParameter("pgi"));
		if (StrUtil.isNotBlank(pgi) && NumberUtil.isNumber(pgi)) {
			siteSearchPage.setSPageId(Long.valueOf(pgi));
		}

		String page = HtmlUtil.escape(request.getParameter("pg"));
		if (StrUtil.isNotBlank(page) && NumberUtil.isNumber(page)) {
			siteSearchPage.setPageNum(Integer.valueOf(page));
		}

		String size = HtmlUtil.escape(request.getParameter("sz"));
		if (StrUtil.isNotBlank(size) && NumberUtil.isNumber(size)) {
			siteSearchPage.setPageSize(Integer.valueOf(size));
		}

		sitePage.setType(PageType.SEARCH).setSiteSearchPage(siteSearchPage);

		SSystem sSystem = null;
		AccessPage accessPage = new AccessPage();
		accessPage.setSitePage(sitePage).setSystem(sSystem);
		requestHolder.set(accessPage);
		// 定义页面渲染后的结果对象
		SRHtml srHtml = new SRHtml();
		siteHolder.setHtml(srHtml);
		return true;
	}

	// 默认情况下执行
	protected boolean page(PageUtil pageUtil, HttpServletResponse response) throws NotFound404Exception, NotFoundSitePageException, JsonParseException,
			JsonMappingException, SitePageException, JsonProcessingException, IOException, NotScreenSystemPageException, NotFoundSiteCategoryException {
		PageService pageServiceImpl = SpringContextUtils.getBean("pageServiceImpl", PageService.class);
		VirtualFolderService virtualFolderServiceImpl = SpringContextUtils.getBean("virtualFolderServiceImpl", VirtualFolderService.class);
		// 通过服务请求获取 SitePage 数据
		SitePage sitePage = null;
		// 首先判断是否是系统详情内容的自定义链接
		SSystemItemCustomLink sSystemItemCustomLink = systemItemCustomLink(pageUtil.getSubstringUri());
		if (sSystemItemCustomLink != null) {
			return makeHolder(pageUtil, sSystemItemCustomLink, sitePage, response);
		}
		// 通过 PageUtil 获取当前页面的 FeignPageUtil 数据
		FeignPageUtil feignPageUtil = pageUtil.getFeignPageUtil(requestHolder.getHostId(), requestHolder.getSiteId());
		try {
			sitePage = pageServiceImpl.getSitePageByFeignPageUtil(feignPageUtil);
		} catch (IOException e) {
		}
		if (sitePage == null || sitePage.getSPage() == null) {
			String uri = requestHolder.getAccessSite().getUri();
			if (virtualFolderServiceImpl.validFileUri(uri)) {
				// 显示虚拟根目录下的内容
				virtualFolderServiceImpl.responseVirtualFolderFileUri(uri, response);
				return false;
			} else {
				// 否则抛出未能通过后缀获取页面信息的页面内容
				logger.error("feignPageUtil 提交的数据异常！feignPageUtil: " + feignPageUtil + " | pageUtil: " + pageUtil);
				return notFoundSitePageExceptionOr404RedirectUrl("未能通过 feignPageUtil 获取到页面数据 feignPageUtil: " + feignPageUtil, response);
			}
		}

		return makeHolder(pageUtil, sitePage, response);
	}

	protected boolean makeHolder(PageUtil pageUtil, SSystemItemCustomLink sSystemItemCustomLink, SitePage sitePage, HttpServletResponse response)
			throws NotFoundSitePageException, SitePageException, IOException {
		sitePage = sitePage(sSystemItemCustomLink);
		if (sitePage == null) {
			logger.error("通过自定义链接的方式未能获取到页面或系统数据信息 sSystemItemCustomLink: " + sSystemItemCustomLink + " | uri: " + pageUtil.getSubstringUri());
			return notFoundSitePageExceptionOr404RedirectUrl(
					"通过自定义链接的方式未能获取到页面或系统数据信息 sSystemItemCustomLink: " + sSystemItemCustomLink + " | uri: " + pageUtil.getSubstringUri(), response);
		}

		Long itemId = sSystemItemCustomLink.getItemId();

		SysStaticDataService sysStaticDataServiceImpl = SpringContextUtils.getBean("sysStaticDataServiceImpl", SysStaticDataService.class);

		// 自定义系统详情内容页面
		sitePage.setTemplateName(
				PageUtil.getTemplateName(sitePage.getSSystem().getSystemTypeId(), sysStaticDataServiceImpl.getSystemTypeInfos(), PageType.ITEM));
		sitePage.setType(PageType.ITEM);
		// 再没有对详情页面定义分类的时候，分类页面的rewrite为item
		sitePage.setRewriteCategory("item");
		sitePage.setRewriteItem(String.valueOf(itemId));

		return makeHolder(sitePage);
	}

	protected boolean makeHolder(PageUtil pageUtil, SitePage sitePage, HttpServletResponse response)
			throws NotFoundSiteCategoryException, NotFoundSitePageException, NotScreenSystemPageException, NotFound404Exception {
		SPage sPage = sitePage.getSPage();
		if (sPage == null || sPage.getStatus() == null || sPage.getStatus().shortValue() == (short) 0) {
			logger.error("sPage 数据异常或者状态为不显示页面！sPage: " + sPage);
			return notFoundSitePageExceptionOr404RedirectUrl("sPage 数据异常或者状态为不显示页面！sPage: " + sPage, response);
		}

		// 甄别页面
		SysStaticDataService sysStaticDataServiceImpl = SpringContextUtils.getBean("sysStaticDataServiceImpl", SysStaticDataService.class);
		boolean bool = false;
		try {
			bool = pageUtil.screenSystemPage(sitePage, sysStaticDataServiceImpl.getSystemTypeInfos());
		} catch (IOException e1) {
			e1.printStackTrace();
		}
		if (!bool) {
			RedirectUrlService redirectUrlServiceImpl = SpringContextUtils.getBean("redirectUrlServiceImpl", RedirectUrlService.class);
			Long hostId = requestHolder.getHost().getId();
			HRedirectUrl hRedirectUrl = null;
			try {
				hRedirectUrl = redirectUrlServiceImpl.findOkOne404ByHostId(hostId);
			} catch (IOException e) {
			}
			if (hRedirectUrl != null) {
				try {
					response.sendRedirect(hRedirectUrl.getToUrl());
				} catch (IOException e) {
					e.printStackTrace();
				}
				return false;
			} else {
				// 给予一个404页面
				logger.error("甄别系统页面出错！ pageUtil: " + pageUtil);
				throw new NotScreenSystemPageException("甄别系统页面出错！ pageUtil: " + pageUtil);
			}
		}

		// 验证是否是系统页面，如果是系统页面获取系统数据信息
		if (sitePage.boolSystem()) {
			// 是否存在分类，如果存在分类 rewriteCategory ，存在则获取分类数据
			sitePageCategory(sitePage, response);

			SSystem sSystem = sitePage.getSSystem();
			String rewriteItem = sitePage.getRewriteItem();
			if (sSystem != null && NumberUtil.isNumber(rewriteItem)) {
				long itemId = NumberUtil.parseLong(rewriteItem);
				if (itemId > 0) {

					SSystemItemCustomLink sSystemItemCustomLink = null;
					try {
						SystemService systemServiceImpl = SpringContextUtils.getBean("systemServiceImpl", SystemService.class);
						sSystemItemCustomLink = systemServiceImpl.findOkOneByHostSiteSystemItemId(sSystem.getHostId(), sSystem.getSiteId(), sSystem.getId(),
								itemId);
					} catch (IOException e) {
					}
					if(sSystemItemCustomLink != null) {
						// 有存在自定义链接的情况下，默认链接不给与访问；
						// 给予一个404页面
						logger.error("存在自定义链接！ sSystemItemCustomLink: " + sSystemItemCustomLink);
						throw new NotFoundSitePageException("存在自定义链接！ sSystemItemCustomLink: " + sSystemItemCustomLink);
					}
				}
			}

		}

		return makeHolder(sitePage);
	}

	protected boolean makeHolder(SitePage sitePage) {
		SPage sPage = sitePage.getSPage();
		SSystem sSystem = sitePage.getSSystem();
		if (sPage == null) {
			return false;
		}

		AccessPage accessPage = new AccessPage();
		accessPage.setSitePage(sitePage).setSystem(sSystem);
		requestHolder.set(accessPage);

		// page 的seo、code数据获取
		long hostId = requestHolder.getHostId();
		long siteId = requestHolder.getSiteId();
		Long pageId = sPage.getId();
		SeoService seoServiceImpl = SpringContextUtils.getBean("seoServiceImpl", SeoService.class);
		SSeoPage sSeoPage = null;
		try {
			sSeoPage = seoServiceImpl.getPageSeoByHostSiteId(hostId, siteId, pageId);
		} catch (IOException e) {
		}
		siteHolder.setSeoPage(sSeoPage);
		SCategories sCategories = sitePage.getSCategories();
		if (sSystem != null && sCategories != null) {
			Long systemId = sSystem.getId();
			Long categoryId = sCategories.getId();
			SSeoCategory sSeoCategory = null;
			try {
				sSeoCategory = seoServiceImpl.getCategorySeoByHostSiteId(hostId, siteId, systemId, categoryId);
			} catch (IOException e) {
			}
			siteHolder.setSeoCategory(sSeoCategory);
		}
		CodeService codeServiceImpl = SpringContextUtils.getBean("codeServiceImpl", CodeService.class);
		SCodePage sCodePage = null;
		try {
			sCodePage = codeServiceImpl.getCodePageByHostSiteId(hostId, siteId, pageId);
		} catch (Exception e) {
		}
		siteHolder.setCodePage(sCodePage);

		// 定义页面渲染后的结果对象
		SRHtml srHtml = new SRHtml();
		siteHolder.setHtml(srHtml);

		return true;
	}

	protected void sitePageCategory(SitePage sitePage, HttpServletResponse response) throws NotFoundSiteCategoryException, NotFoundSitePageException {
		CategoryService categoryServiceImpl = SpringContextUtils.getBean("categoryServiceImpl", CategoryService.class);
		SSystem sSystem = sitePage.getSSystem();
		String rewriteCategory = sitePage.getRewriteCategory();
		if (StringUtils.isEmpty(rewriteCategory) || sSystem == null) {
			return;
		}
		if ("item".equals(rewriteCategory) || "index".equals(rewriteCategory)) {
			return;
		}
		Long categoryId = null;
		if (!NumberUtil.isNumber(rewriteCategory)) {
			notFoundSitePageExceptionOr404RedirectUrl("无法识别页面！ siteUri: " + requestHolder.getAccessSite().getUri(), response);
			return;
		}
		try {
			categoryId = Long.valueOf(rewriteCategory);
		} catch (NumberFormatException e) {

			throw new NotFoundSiteCategoryException("未能通 rewriteCategory 无法转换成可识别数字！ rewriteCategory： " + rewriteCategory);
		}
		if (categoryId == null || categoryId.longValue() < 1) {
			return;
		}
		// 获取分类数据
		SCategories sCategories = null;
		try {
			sCategories = categoryServiceImpl.getInfoByHostCategoryId(sSystem.getHostId(), sSystem.getId(), categoryId);
		} catch (IOException e) {
			e.printStackTrace();
		}
		if (sCategories == null) {
			// 未能通过uri上的分类 rewrite 部分获取到分类数据
			throw new NotFoundSiteCategoryException(
					"未能通 rewriteCategory 过找对应的 category 数据！systemId: " + sSystem.getId() + " rewriteCategory： " + rewriteCategory);
		}
		sitePage.setSCategories(sCategories);
	}

	protected SSystemItemCustomLink systemItemCustomLink(String substringUri) {
		long hostId = requestHolder.getHostId();
		long siteId = requestHolder.getSiteId();

		SSystemItemCustomLink sSystemItemCustomLink = null;
		try {
			SystemService systemServiceImpl = SpringContextUtils.getBean("systemServiceImpl", SystemService.class);
			sSystemItemCustomLink = systemServiceImpl.findOkOneByHostSiteIdAndPathFinal(hostId, siteId, substringUri);
		} catch (IOException e) {
			e.printStackTrace();
		}

		return sSystemItemCustomLink;
	}

	protected SitePage sitePage(SSystemItemCustomLink sSystemItemCustomLink) {
		SitePage sitePage = null;
		Long hostId = sSystemItemCustomLink.getHostId();
		Long siteId = sSystemItemCustomLink.getSiteId();
		Long systemId = sSystemItemCustomLink.getSystemId();

		SSystem sSystem = null;
		SystemService systemServiceImpl = SpringContextUtils.getBean("systemServiceImpl", SystemService.class);
		try {
			sSystem = systemServiceImpl.findInfo(hostId, siteId, systemId);
		} catch (IOException e1) {
		}

		if (sSystem == null) {
			return null;
		}
		SPage sPage = null;
		PageService pageServiceImpl = SpringContextUtils.getBean("pageServiceImpl", PageService.class);
		try {
			sPage = pageServiceImpl.getPageByHostSiteSystemId(hostId, siteId, systemId);
		} catch (IOException e) {
		}
		if (sPage == null) {
			return null;
		}

		sitePage = new SitePage();
		sitePage.setSPage(sPage).setSSystem(sSystem);

		return sitePage;
	}

	/**
	 * 要么抛出异常，要么返回404页面重定向的url链接地址
	 * 
	 * @param response
	 * @throws NotFoundSitePageException
	 */
	protected boolean notFoundSitePageExceptionOr404RedirectUrl(String message, HttpServletResponse response) throws NotFoundSitePageException {
		RedirectUrlService redirectUrlServiceImpl = SpringContextUtils.getBean("redirectUrlServiceImpl", RedirectUrlService.class);
		Long hostId = requestHolder.getHost().getId();
		HRedirectUrl hRedirectUrl = null;
		try {
			hRedirectUrl = redirectUrlServiceImpl.findOkOne404ByHostId(hostId);
		} catch (IOException e) {
		}
		if (hRedirectUrl != null) {
			try {
				response.sendRedirect(hRedirectUrl.getToUrl());
			} catch (IOException e) {
				e.printStackTrace();
			}
		} else {
			// 给予一个404页面
			throw new NotFoundSitePageException(message);
		}
		return false;
	}

	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
	}

	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

	}

}
